%xdefine chr (rbp-8)
%xdefine tmp (rbp-16)

%include "macroses.inc"

global Fscanf
global ReadString
global ReadDecimal

;| input
;rax == buf
;rdi == fd
;| output
;rdx == last read char
ReadDecimal:
    push rbp 
    mov rbp, rsp

    sub rsp, 8

    mov qword [chr], 0
    
    push rcx
    push rbx

    xor rcx, rcx
    xor rbx, rbx
    .next_iter:
        READ_CHAR chr, rdi
        CHECK_SPECIAL [chr]
        je .is_first_char
        
        cmp byte [chr], '-'
        je .is_neg

        CHECK_NUMBER [chr]
        je .is_number
        
        jmp .ret

        .is_first_char:
            cmp rcx, 0
            je .next_iter

            jmp .ret

        .is_neg:
            cmp rcx, 0
            ja  .ret

            neg qword [rax]
            jmp .next_iter

        .is_number:
            sub byte [chr], 48
            mov rbx, [rax] 
            imul rbx, 10

            add rbx, [chr]
            mov [rax], rbx
            
            inc rcx
            jmp .next_iter
    .ret:        
        mov rdx, [chr]
        pop rbx
        pop rcx

        add rsp, 8

        pop rbp
        ret


 

;| input
;rax == buf
;rdi == fd
;| output
;rdx == last read char
ReadString:
    push rbp
    mov rbp, rsp

    sub rsp, 16
    
    mov qword [chr], 0

    push rbx
    
    mov [tmp], rax
    .next_iter:
        READ_CHAR chr, rdi
        CHECK_SPECIAL [chr]
        je .is_first_char
        
        mov bl, [chr] 
        mov [rax], bl
        inc rax
        jmp .next_iter
        
        .is_first_char:
            cmp [tmp], rax
            je .next_iter

            jmp .ret

    .ret:
        mov rdx, [chr]
        pop rbx
        add rsp, 16
        pop rbp
        ret


;| input
; rdi == fd
; rax == format
; arg == stack
;| output
; rax == number proccesing chars
Fscanf:
    push rbp
    mov rbp, rsp
    sub rsp, 8 
    
    mov qword [chr], 0
    
    push rcx
    push rdx
    push rbx
    push rdi
    
    xor rbx, rbx
    xor rcx, rcx
    xor rdx, rdx
    .next_iter:
        cmp [rax], byte 0x0 
        je .ret

        cmp [rax], byte '%'
        je .format_char

        mov cl, [rax]
        mov [chr], cl
        CHECK_SPECIAL [chr] 
        je .special_char

        jmp .default_char

        .format_char:
            inc rax
            
            cmp [rax], byte 's'
            je .read_string

            cmp [rax], byte 'd'
            je .read_decimal

            cmp [rax], byte 'c'
            je .read_char

            jmp .ret

        .read_string:
            push rax
            mov rax, [next_arg]

            cmp dl, 0x0
            je .skip_push_char
            
            mov [chr], dl
            CHECK_SPECIAL [chr]
            je .skip_push_char

            mov [rax], dl
            inc rax

            .skip_push_char:
                call ReadString

                pop rax
                inc rbx
                xor rdx, rdx

            jmp .next_step
            
        .read_decimal:
            push rax
            mov rax, [next_arg]

            call ReadDecimal

            pop rax
            inc rbx

            jmp .next_step
        
        .read_char:
            push rax

            cmp dl, 0x0
            je .skip_push_char2

            mov [chr], dl
            CHECK_SPECIAL [chr]
            je .skip_push_char2
            
            mov rcx, [next_arg]
            mov [rcx], dl
            xor rdx, rdx
            jmp .read_char_end

            .skip_push_char2:
                READ_CHAR chr, rdi
                CHECK_SPECIAL [chr]
                je .skip_push_char2

                mov al, [chr]
                mov rcx, [next_arg]
                mov [rcx], al

            .read_char_end:
                pop rax
                inc rbx
                jmp .next_step

        .special_char:
            inc rax
            mov cl, [rax]
            mov [chr], cl

            CHECK_SPECIAL [chr]
            je .special_char

            jmp .next_iter

        .default_char:
            cmp dl, 0x0
            je .skip_push_char3

            cmp dl, [rax]
            je .del_dl

            .del_dl:
                xor rdx, rdx
                jmp .next_step

            jmp .ret

            .skip_push_char3:
                READ_CHAR chr, rdi

                mov cl, [chr]
                cmp cl, [rax]
                je .next_step

                jmp .ret
        
        .next_step:
            inc rax
            jmp .next_iter
    
    .ret:
        mov rax, rbx

        pop rdi
        pop rbx
        pop rdx
        pop rcx
        add rsp, 8
        pop rbp
        ret


